'''
上传房源图片接口文档
请求方式：post
请求路径：/api/v1.0/houses/(?P<house_id>\d+)/images/
请求参数：house_image
        file
响应：JSON
errno   RET.OK      必传
errmsg  OK      必传
data    URL:上传图片url链接  必传
'''
import json
from datetime import datetime

from django.core.paginator import Paginator
from django.http import JsonResponse
from django.views import View

from aijia_zufang.settings.dev import logger, QINIU_DOMIN_PREFIX
from aijia_zufang.utils.image_storage import storage
from aijia_zufang.utils.response_code import RET
from aijia_zufang.utils.views import LoginRequiredJSONMixin
from apps.address.models import Area
from apps.house.models import House, Facility, HouseImage
from apps.house.until import all_house_detil
from apps.orders.models import Order
class UploadHouseImage(View):

    def post(self,request,house_id):

        # 获取上传的图片
        huose_image = request.FILES.get('house_image')

        if not huose_image:
            return JsonResponse({'errno': RET.PARAMERR, 'errmsg': "未上传图片"})

        # 查询房屋是否存在
        try:
            house = House.objects.get(pk=house_id)
        except Exception as e:
            logger(e)
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "房屋不存在"})
        # 将上传的图片保存到七牛云
        image_data = huose_image.read()
        try:
            file_name = storage(image_data)
        except Exception as e:
            logger(e)
            return JsonResponse({'errno': RET.PARAMERR, 'errmsg': "图片上传失败"})
        try:
            house_image = HouseImage.objects.create(house=house, url=file_name)
        except Exception as e:
            logger.error(e)
            return JsonResponse({'errno': RET.DBERR, 'errmsg': "保存数据失败"})
        try:
            house.index_image_url = file_name
            house.save()
        except Exception as e:
            logger(e)
            return JsonResponse({'errno': RET.PARAMERR, 'errmsg': "图片保存失败"})
        url = QINIU_DOMIN_PREFIX + file_name
        # 返回结果
        return JsonResponse({'errno': RET.OK, 'errmsg': "OK", 'data': {"url": url}})
'''
房屋首页推荐
路由'api/v1.0/houses/index/', views.AdvertisingRecommendation.as_view()
返回正确返回
{
    'data': [
        {'house_id': 4, 'img_url': 'xxx', 'title': 'xxx'},
        {...},
        {...},
        .......
    ],
    'errmsg': 'OK',
    'errno': '0'
}
错误返回
（{'code': 4002, 'errmsg': 'NODATA'}）
返回字段：house——id
int
房屋id
img_url
str
房屋主图片
title
str
房屋标题

'''
class AdvertisingRecommendation(View):
    # 首页广告推荐，推荐原则：订购量排序。数据在Houses表中。
    def get(self, request):
        # 1.拉取数据，从House中通过order_count，来排序房屋
        order_by_houses = House.objects.all().order_by('-order_count')
        # 2.从首页看出首页房屋推荐图为3个,当数据库有大于等3个数据时，将其切割出3个。
        if order_by_houses.count() >= 3:
            carousel_houses = order_by_houses[:3]
        else:
            return JsonResponse({'code':400,'errmsg':'没有广告'})
        # 已知给出的返回值模型为data:[{houses_id:,img_url:,title:},{},{}]
        data_house= []
        for house in carousel_houses:
              data_house.append({
                  'house_id':house.id,
                  'img_url':QINIU_DOMIN_PREFIX + house.index_image_url,
                  'title':house.title,
              })
        return JsonResponse({'errno':0,'errmsg':'ok','data':data_house})
# 房屋搜索
"""
请求方式：get
路由：api/v1.0/houses/serch/,views.SearchFor.as_view()
传参：aid   int 区域id
     sd    str 开始日期
     ed    str  结束时间
     sk    str  排序方式booking（订单量），price-inc(从低到高)，price-des(从高到低)
     p     int  页数，不传默认为1
     返回值  {'data':{total_page:1,'houses':[{house_id:,order_count:,title:,
     ctime:,price:,area_name:,address:,room_count:,img_url:,user_avatar:
     }]},
     'code':0,'errmsg':'请求成功'}
"""
class SearchFor(View):
    def get(self,request):
        # 接受参数
        search_transfer = request.GET
        # 1.区域id
        erea_id = search_transfer.get('aid',)
        # 2.开始时间
        sd = search_transfer.get('sd',)
        # 3.结束时间
        ed = search_transfer.get('ed',)
        # 4.排序方式
        sk = search_transfer.get('sk',)
        # 5.页数，不传默认为1
        p = search_transfer.get('p',1)
        # 2.效验参数
        try:
            page = int(p)
        except Exception as e:
            return JsonResponse({'code':400,'errmsg':'没有此区域'})
         # 日期格式转换
        try:
            sd_start = None
            ed_end = None
            if sd:
                sd_start = datetime.strptime(sd,'%Y-%m-%d')
            if ed:
                ed_end = datetime.strptime(ed,'%Y-%m-%d')
            # 开始时间小于结束时间
            if sd_start and ed_end:
                assert sd_start < ed_end, Exception('开始时间大于结束时间')
        except Exception as e:
            return JsonResponse({'code':400,'errmsg':'参数错误'})
        houses_object = {}
        # 判断是否传入城区id
        if erea_id:
            houses_object['area_id'] = erea_id
        houses_objects = House.objects.filter(**houses_object)
        # 过滤已经预购的房屋
        conflict_oder = None
        if not Order.objects.all():
            conflict_oder = None
        else:
            try:
                if sd_start and ed_end:
                    # 已订购的房屋中，开始时间小于等于 用户预定入住时间,结束时间大于用户预定退房时间
                    conflict_oder = Order.objects.fliter(begin_date__lte = sd_start, end_date__gte = ed_end)
                elif sd_start:
                    # 数据库存在已经订购的房屋 退房时间大于用户输入的开始入住时间
                    conflict_oder = Order.objects.fliter(end_data__gte = sd_start)
                elif ed_end:
                    # 数据库存在已经订购的房屋，开始时间小于等于用户输入的结束的时间
                    conflict_oder = Order.objects.fliter(begin_date__lte = ed_end)
            except Exception as e:
                return JsonResponse({'code':RET.NODATA,'errmsg':'无数据'})
        if conflict_oder:
            # 获取有冲突的房屋的id
            # 从冲突房屋中遍历，从遍历出来的冲突房屋对象中取出房屋id,放到列表
            conflict_oder_id = [order.house_id for order in conflict_oder]
            # exclude 排除符合条件的 (如果冲突id 在房屋id内存在)
            houses_objects = houses_objects.exclude(id__in = conflict_oder_id)
        # 根据筛选条件查询
        # booking（订单量），price-inc(从低到高)，price-des(从高到低)
        if sk == 'booking':
            # 订单量排序由高到低
            houses_objects = houses_objects.order_by('-order_count')
        elif sk == 'price-inc':
            # 价格由低到高
            houses_objects= houses_objects.order_by('price')
        elif sk == 'price-des':
            # 价格由高到低
            houses_objects = houses_objects.order_by('-price')
        # 用分页器将符合的房屋信息分页
        paginator = Paginator(houses_objects,5)
        # 获取指定页的房屋数据
        houses_objects_pages = paginator.page(p)
        # 获取列表页总数
        total_page = paginator.num_pages

        # 将查询结果转为字符串
        houses_list = []
        for houses_objects_page in houses_objects_pages:
            houses_list.append({
                  'house_id':houses_objects_page.id,
                  'order_count':houses_objects_page.order_count,
                  'title':houses_objects_page.title,
                  'ctime':houses_objects_page.create_time.strftime('%Y-%m-%d'),
                  'price':houses_objects_page.price,
                  # 多找一
                  'area_name':houses_objects_page.area.name,
                  'address':houses_objects_page.address,
                  'room_count':houses_objects_page.room_count,
                  'img_url':QINIU_DOMIN_PREFIX + houses_objects_page.index_image_url,
                  # 多找一
                  'user_avatar':houses_objects_page.user.avatar_url,
            })
        response_data = {'total_page':total_page,'houses':houses_list}
        return JsonResponse({'errno':0,'errmsg':'ok','data':response_data})
# 发布新房源信息
class HouseReleaseView(LoginRequiredJSONMixin, View):

    def post(self, request):

        # 1. 使用请求体获取参数并且转换格式为--->str
        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')  # 房源标题
        price = json_dict.get('price')  # 每晚价格
        address = json_dict.get('address')  # 详细地址
        area_id = json_dict.get('area_id')  # 所在地区id
        room_count = json_dict.get('room_count')  # 出租房屋数目
        acreage = json_dict.get('acreage')  # 房屋面积
        unit = json_dict.get('unit')  #户型描述，如：二室一厅一卫一厨
        capacity = json_dict.get('capacity')  # 宜住人数
        beds = json_dict.get('beds')  # 卧床配置
        deposit = json_dict.get('deposit')  # 押金数额
        min_days = json_dict.get('min_days')  # 最少入住天数
        max_days = json_dict.get('max_days')  # 最多入住天数

        # 2. 判断上面的参数是否都有值
        if not all(
            [title, price, address, area_id, room_count, acreage, unit, capacity, beds, deposit, min_days, max_days]
        ):
            return JsonResponse({'errno': RET.PARAMERR, 'errmsg': '参数有误！'})

        # 3. 校验参数是否正确
        # 3.1 校验区域 id 参数是否正确
        try:
            area = Area.objects.get(id=area_id)
        except Exception as e:
            print(e)
            return JsonResponse({'errno': RET.PARAMERR, 'errmsg': "区域参数有误！"})
        # 3.2 校验所有新增参数是否有误
        try:
            house = House.objects.create(user=request.user, area=area, title=title, price=price, address=address,
                                         room_count=room_count, acreage=acreage, unit=unit, capacity=capacity,
                                         beds=beds, deposit=deposit, min_days=min_days, max_days=max_days)
        except Exception as e:
            print(e)
            return JsonResponse({'errno': RET.DBERR, 'errmsg': "新增到数据库有误！"})

        # 4. 获取到当前房屋的设施列表数组
        facilities = json_dict.get("facility")
        facilities = Facility.objects.filter(id__in=facilities)
        house.facilities.add(*facilities)

        # 5. 保存 house 模型到数据库
        try:
            house.save()
        except Exception as e:
            print(e)
            return JsonResponse({'errno': RET.DBERR, 'errmsg': "数据保存失败!"})

        return JsonResponse({'errno': RET.OK, 'errmsg': "Ok!", 'data': {"house_id": house.id}})
'''
接口文档：
路径 URL：api/v1.0/houses/<int:house_id>/      通过house_id 进行路径参数

请求方式 get， 接收时候 接收路径参数house_id

参数：
返回值字段	类型	    字段说明
user_id	    int	    当前登录用户的用户id，如果没有登录，则为 -1
house	    dict	房屋详细信息

house
返回值字段	类型	    字段说明
acreage	    int	    房屋面积
title	    str	    标题
price	    str	    价格
area_id	    int	    城区id
address	    str	    房屋地址
room_count	int	    房间数目
unit	    str	    房屋单元，如：几室几厅
capacity 是	int	    房屋容纳的人数
beds	    str	    房屋床铺的配置
deposit	    str	    房屋押金
min_days	int	    最少入住天数
max_days	int	    最大入住天数，0表示不限制
facilities	array	设施信息id列表，如：[7, 8]
hid	        int	    房屋ID
comments	array	该房屋的评论列表
img_urls	array	房屋图片列表
user_avatar	str	    该房屋所有者的头像
user_id	    str	    该房屋所有者的用户id
user_name	str	    该房屋所有者的昵称

comments
返回值字段	    类型	    字段说明
comment	        str	    评论内容
ctime	        str	    评论时间
user_name	    str	    评论人昵称


响应方式，json
'''
# 房屋详情
# 相应对象house:{}
class HouseDetailsView(View):
    def get(self, request, house_id):
        # 1.获取house模型类对应id的对应内容
        user_id = request.user.id

        # 获取 House表下面的 所有数据 根据当前 房屋id进行筛选
        try:
            all_house = House.objects.get(id=house_id)
        except:
            return JsonResponse({'errno': RET.PARAMERR, 'errmsg': "error 房屋id有问题"})
        house = {
            'acreage': all_house.acreage,
            'address': all_house.address,
            'beds': all_house.beds,
            'capacity': all_house.capacity,

            'comments':[],

            'deposit': all_house.deposit,

            'facilities':[],

            'hid': all_house.id,

            'img_urls':[],

            'max_days': all_house.max_days,
            'min_days': all_house.min_days,
            'price': all_house.price,
            'room_count': all_house.room_count,
            'title': all_house.title,
            'unit': all_house.unit,
            'user_avatar':all_house.user.avatar_url,
            'user_id':all_house.user.id,
            'user_name':all_house.user.username,

            'area_id': all_house.area_id,
        }
        '''
        下面是用来补充上面 字典的 k键的，需要的是图片url和设施信息id列表
        '''
        # 获取图片
        img_urls = []
        # 一找多 一个房子 找多张图片 用模型类小写
        imgs_urls = all_house.houseimage_set.all()
        # 获取到对应的图片 获取url
        for img in imgs_urls:
            img_urls.append(QINIU_DOMIN_PREFIX + img.url)
            # 给字典添加key 和v
        house['img_urls'] =  img_urls
        # 设施信息id列表
        facilities = []
        for facility in all_house.facilities.all():
            facilities.append(facility.id)
        house["facilities"] = facilities
        # 获取评论 把评论添加进表格。并且添加到字典detail里面
        comments = []
        # 要找到评论表里面，该房子对应的评论 连接Orders表
        comment = Order.objects.filter(house=all_house.id, status='COMPLETE')
        for com in comment:
            com = {
                "comment": com.comment,  # 评论的内容
                "user_name": com.user.username if com.user.username != com.user.mobile else "匿名用户",  # 发表评论的用户
                "ctime": com.update_time.strftime("%Y-%m-%d %H:%M:%S")  # 评价的时间
            }
            comments.append(com)
        house['comments'] = comments
        # 2.设置初始字典 然后在最后返回用
        # detail = all_house_detil

        return JsonResponse({'errno': RET.OK, 'errmsg': "OK", 'data': {"user_id": user_id, "house": house}})

